package expressions;

import exceptions.ParserException;
import parsing.Parser;

/**
 * The base class for expression trees. To create an expression, use a Parser
 * instance; then call evaluate (with the proper context) to evaluate the
 * expression.
 * 
 * @param <T>
 *            the type which this expression calculates with.
 */
public abstract class Expression<T>
{

    /**
     * Does the relevant step of the Shunting-Yard algorithm to parse the token
     * corresponding to this expression.
     * 
     * By default, the expression just gets sent to the output stack -- this is
     * appropriate behavior for e.g. constants.
     * 
     * @param parser
     *            The parser that's trying to parse this expression.
     */
    public void parse(Parser<T> parser)
    {
        parser.output(this);
    }

    /**
     * Evaluates the expression.
     * 
     * @param context
     *            The context within which the expression is evaluated; this
     *            supplies the values of variables and things like that.
     * 
     * @return The value of the expression.
     */
    public abstract T evaluate(IContext<T> context);

    /**
     * Another step in parsing the expression; this method gets called when it's
     * time to transfer an expression from the operator stack to the output
     * stack.
     * 
     * This method should be defined for all expression types, but it doesn't
     * make sense for things that are never on the operator stack, so the
     * default action is to throw an exception.
     * 
     * @param parser
     *            The parser that's trying to parse this expression.
     */
    public void buildTree(Parser<T> parser)
    {
        throw new ParserException();
    }
}
